#ifndef ODBCTESTS_MYSQL_RECORD_SAMPLE_HPP
#define ODBCTESTS_MYSQL_RECORD_SAMPLE_HPP

#include "odbc/statement.hpp"
#include <boost/any.hpp>
#include <boost/tuple/tuple.hpp>

namespace odbc_tests
{

/// \ingroup odbc_tests
/// \brief It is the tuple type to be used for queries
typedef boost::tuples::tuple
	< 
		unsigned char,		// TINYINT_FIELD
		unsigned char,		// BOOL_FIELD
		short,				// SMALLINT_FIELD
		short,				// MEDIUMINT_FIELD
		int,				// INT_FIELD
		long,				// BIGINT_FIELD
		float,				// FLOAT_FIELD
		double,				// DOUBLE_FIELD
		std::string,		// VARCHAR_FIELD
		boost::posix_time::ptime				// DATETIME_FIELD
	> queried_record;


/// \ingroup OdbcTests
/// \brief
/// It provides a structure for defining record data to be used in testing.
struct record_sample
{
	/// \brief It initializes the data.
	record_sample( 	
		unsigned char tinyIntValue, unsigned char boolValue, short smallIntValue, short mediumIntValue, int intValue, long bigIntValue, 
		float floatValue, double doubleValue, 
		const std::string& varcharValue, 
		const boost::posix_time::ptime& dateTimeValue)
		: tinyIntValue_( tinyIntValue), boolValue_( boolValue), smallIntValue_( smallIntValue), mediumIntValue_( mediumIntValue), intValue_( intValue), bigIntValue_( bigIntValue)
		, floatValue_( floatValue), doubleValue_( doubleValue), varcharValue_( varcharValue), dateTimeValue_( dateTimeValue)
	{
	}

	/// \brief It uses the data as parameters to the provided statement.
	void add_param_to_statement( odbc::statement& stat)
	{
		stat.add_parameter( tinyIntValue_);
		stat.add_parameter( boolValue_);
		stat.add_parameter( smallIntValue_);
		stat.add_parameter( mediumIntValue_);
		stat.add_parameter( intValue_);
		stat.add_parameter( bigIntValue_);
		stat.add_parameter( floatValue_);
		stat.add_parameter( doubleValue_);
		stat.add_parameter( varcharValue_);
		stat.add_parameter( dateTimeValue_);
	}

	/// \brief It adds null parameter values to the given statement.
	static void add_null_param_to_statement( odbc::statement& stat)
	{
		using namespace odbc;
		stat.add_parameter<unsigned char>( parameter::in);
		stat.add_parameter<unsigned char>( parameter::in);
		stat.add_parameter<short>( parameter::in);
		stat.add_parameter<short>( parameter::in);
		stat.add_parameter<int>( parameter::in);
		stat.add_parameter<long>( parameter::in);
		stat.add_parameter<float>( parameter::in);
		stat.add_parameter<double>( parameter::in);
		stat.add_parameter<std::string>( parameter::in);
		stat.add_parameter<boost::posix_time::ptime>( parameter::in);
	}

	/// \brief It uses the data as parameters to the provided statement.
	/// \pre The parameter binding is already done.
	void set_param_to_statement( odbc::statement& stat)
	{
		stat.set_parameter( 0, tinyIntValue_);
		stat.set_parameter( 1, boolValue_);
		stat.set_parameter( 2, smallIntValue_);
		stat.set_parameter( 3, mediumIntValue_);
		stat.set_parameter( 4, intValue_);
		stat.set_parameter( 5, bigIntValue_);
		stat.set_parameter( 6, floatValue_);
		stat.set_parameter( 7, doubleValue_);
		stat.set_parameter( 8, varcharValue_);
		stat.set_parameter( 9, dateTimeValue_);
	}

	/// \brief It sets null parameter values to the given statement.
	static void set_null_param_to_statement( odbc::statement& stat)
	{
		stat.set_parameter( 0, boost::any());
		stat.set_parameter( 1, boost::any());
		stat.set_parameter( 2, boost::any());
		stat.set_parameter( 3, boost::any());
		stat.set_parameter( 4, boost::any());
		stat.set_parameter( 5, boost::any());
		stat.set_parameter( 6, boost::any());
		stat.set_parameter( 7, boost::any());
		stat.set_parameter( 8, boost::any());
		stat.set_parameter( 9, boost::any());
	}

	unsigned char tinyIntValue_;
	unsigned char boolValue_;
	short smallIntValue_;
	short mediumIntValue_;
	int intValue_;
	long bigIntValue_;
	float floatValue_;
	double doubleValue_;
	std::string varcharValue_;
	boost::posix_time::ptime dateTimeValue_;
};

#define ODBCTEST_CHECK_RECORD( ITER, REC) \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[0], unsigned char, REC.tinyIntValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[1], unsigned char, REC.boolValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[2], short, REC.smallIntValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[3], short, REC.mediumIntValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[4], int, REC.intValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[5], long, REC.bigIntValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[6], float, REC.floatValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[7], double, REC.doubleValue_); \
	ODBCTEST_CHECK_FIELD_EQUAL( (*ITER)[8], std::string, REC.varcharValue_); \
	ODBCTEST_CHECK_FIELD( (*ITER)[9], ptime, REC.dateTimeValue_)

#define ODBCTEST_CHECK_NULL_RECORD( ITER) \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[0]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[1]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[2]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[3]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[4]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[4]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[5]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[6]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[7]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[8]); \
	ODBCTEST_CHECK_NULL_FIELD( (*iter)[9])

} // namespace odbc_tests

#endif // ODBCTESTS_MYSQL_RECORD_SAMPLE_HPP
